package com.rois.librois.libRoISProfileManager;

import java.io.File;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.rois.librois.RoIS.ComponentProfile;
import com.rois.librois.RoIS.ComponentProfileHolder;
import com.rois.librois.libRoISMessageStorage.RoIS_Components;

/**
 * API for reading profile in XML format.
 * This object holds profile information using RoIS_Components class.
 *
 * @author Miki Sato <miki.sato.1225@gmail.com>
 *
 *    The MIT licence
 *
 *    Copyright (C) 2011
 *      ATR Intelligent Robotics and Communication Laboratories, Japan
 *
 *    Permission is hereby granted, free of charge, to any person obtaining a copy
 *    of this software and associated documentation files (the "Software"), to deal
 *    in the Software without restriction, including without limitation the rights
 *    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 *    of the Software, and to permit persons to whom the Software is furnished to do so,
 *    subject to the following conditions:
 *
 *    The above copyright notice and this permission notice shall be included in all
 *    copies or substantial portions of the Software.
 *
 *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 *    INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 *    PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 *    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 *    OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 *    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

public class Profiles {
	private Object m_hMutex = new Object();
	private String m_strFileName = "";
	private String m_strDir;
	public RoIS_Components m_Components = new RoIS_Components();


	/**
	 * Open Profile XML file.
	 * @param filename path for the XML file
	 * @return Document object
	 */
	private	Document openXmlFile(
		String filename			// in :profile path
	)
	{
		Document docRes = null;

		// save filename
		m_strFileName = "";
		if(filename=="")
		{
			return docRes;
		}
		m_strFileName = filename;

		// create document builder
		File file;
		DocumentBuilderFactory factory;
		DocumentBuilder builder;
		try{
			file = new File(m_strFileName);
			factory = DocumentBuilderFactory.newInstance();
			factory.setIgnoringElementContentWhitespace(true);
			builder = factory.newDocumentBuilder();
			docRes = builder.parse(file);
		}
		catch(Exception e)
		{
			e.printStackTrace();
			return docRes;
		}

		return docRes;
	}

	/**
	 * close Profile XML file.
	 * @param pDoc Document object
	 * @returntrue/false
	 */
	private boolean closeXmlFile(
		Document pDoc				// in :document pointer
	)
	{
		boolean bRes = false;
		pDoc = null;
		bRes = true;
		return bRes;
	}

	/**
	 * remove white space in a text.
	 * @param in_string input text
	 * @return output text
	 */
	private String trimWhiteSpace(
		String in_string
	)
	{
	    String strRes = null;
		char w_char;
	    int w_sindex = 0;
	    int w_eindex = 0;
	    if (in_string != null)
	    {
	        for(w_eindex = in_string.length() -1; w_eindex >= 0; w_eindex--)
	        {
	            w_char = in_string.charAt(w_eindex);
	            if (Character.isWhitespace(w_char))
	            { continue; }
	            else
	            {
	                for (w_sindex = 0; w_sindex < w_eindex; w_sindex++)
	                {
	                    w_char = in_string.charAt(w_sindex);
	                    if (Character.isWhitespace(w_char))
	    	            { continue; }
	                    else
	                    { break; }
	                }
	                break;
	            }
	        }
	        strRes = in_string.substring(w_sindex, ++w_eindex);
	    }
	    return strRes;
	}

	//@@ FOR DUMMY: for file operation
	//@@ default directory is the current directory only (tentatively)
	//@@ please change directory path by "setCurrentDirectory", if you want to use other directory,
	/**
	 * set directory path of Profile XML file.
	 * @param path path of the directory
	 */
	public void setCurrentDirectory(
		String path					// in :path
	)
	{
		m_strDir = path;
	}

	/**
	 * get directory path of Profile XML file.
	 * @return path of the directory
	 */
	public String getCurrentDirectory()
	{
		String strRes = m_strDir;
		return strRes;
	}

	/**
	 * get component profile IDs from Engine profile
	 * @param filename file path of Engine profile
	 * @param components (out) list of component profile IDs
	 * @return number of components
	 */
	public int getComponentProfiles(
		String filename,			// in :profile path
		Vector<String> components	// out:list of profile IDs
	)
	{
		int iRes = 0;
		synchronized( m_hMutex )
		{
			// open file
			Document pDoc = openXmlFile(m_strDir+filename);
			if(pDoc==null)
			{
				return iRes;
			}

			// read xml file
			NodeList plEng = pDoc.getElementsByTagName("HRIEngineProfile");
			Element peEng = (Element) plEng.item(0);

			NodeList plCmp = peEng.getElementsByTagName("HRIComponent");
			iRes = plCmp.getLength();
			for(int i=0; i<iRes; i++)
			{
				Element peCmp = (Element) plCmp.item(i);
				if(peCmp.getTagName().equals("HRIComponent"))	// @@ double check
				{
					String strTemp = peCmp.getTextContent();
					strTemp = this.trimWhiteSpace(strTemp);
					components.add(strTemp);
				}
			}

			// close file
			closeXmlFile(pDoc);
		}
		return iRes;
	}

	/**
	 * get sub component profile IDs from Component profile.
	 * @param filename file path of Component profile
	 * @param subcomponents (out) list of sub component profile IDs
	 * @return number of sub components
	 */
	public int getSubComponentProfiles(
		String filename,				// in :profile path
		Vector<String> subcomponents	// out:list of profile IDs
	)
	{
		int iRes = 0;
		synchronized( m_hMutex )
		{
			// open file
			Document pDoc = openXmlFile(m_strDir+filename);
			if(pDoc==null)
			{
				return iRes;
			}

			// read xml file
			NodeList plCmp = pDoc.getElementsByTagName("HRIComponentProfile");
			Element peCmp = (Element) plCmp.item(0);

			NodeList plItem = peCmp.getElementsByTagName("SubComponentProfile");
			iRes = plItem.getLength();
			for(int i=0; i<iRes; i++)
			{
				Element peItem = (Element) plItem.item(i);
				if(peItem.getTagName().equals("SubComponentProfile"));	//@@ double check
				String strTemp = peItem.getTextContent();
				strTemp = this.trimWhiteSpace(strTemp);
				subcomponents.add(strTemp+".xml");
			}

			// close file
			closeXmlFile(pDoc);
		}
		return iRes;
	}

	/**
	 * check presence of sub component in Component profile.
	 * @param filename file path of Component profile
	 * @return true/false
	 */
	public boolean isSubComponentProfile(
		String filename			// in :profile path
	)
	{
		boolean bRes = false;
		synchronized( m_hMutex )
		{
			// open file
			Document pDoc = openXmlFile(m_strDir+filename);
			if(pDoc==null)
			{
				return bRes;
			}

			// read xml file
			NodeList plCmp = pDoc.getElementsByTagName("HRIComponentProfile");
			Element peCmp = (Element) plCmp.item(0);

			NodeList plItem = peCmp.getElementsByTagName("SubComponentProfile");
			if(plItem!=null)
			{
				if(plItem.getLength()!=0)
				{
					bRes = true;
				}
			}

			// close file
			closeXmlFile(pDoc);
		}
		return bRes;
	}

	/**
	 * get component name in Component profile.
	 * @param filename file path of Component profile
	 * @return component name
	 */
	public String getComponentName(
		String filename			// in :profile path
	)
	{
		String strRes = "";
		synchronized( m_hMutex )
		{
			// open file
			Document pDoc = openXmlFile(m_strDir+filename);
			if(pDoc==null)
			{
				return strRes;
			}

			// read xml file
			NodeList plCmp = pDoc.getElementsByTagName("HRIComponentProfile");
			Element peCmp = (Element) plCmp.item(0);

			NodeList plItem = peCmp.getElementsByTagName("name");
			int iNum = plItem.getLength();
			if(iNum==1)
			{
				Element peItem = (Element) plItem.item(0);
				if(peItem!=null)
				{
					strRes = peItem.getTextContent();
				}
			}

			// close file
			closeXmlFile(pDoc);
		}
		return strRes;
	}

	/**
	 * get component reference ID in Component profile.
	 * @param filename file path of Component profile
	 * @return component reference ID
	 */
	public String getComponentRef(
		String filename			// in :profile path
	)
	{
		String strRes = "";
		synchronized( m_hMutex )
		{
			// open file
			Document pDoc = openXmlFile(m_strDir+filename);
			if(pDoc==null)
			{
				return strRes;
			}

			// read xml file
			NodeList plCmp = pDoc.getElementsByTagName("HRIComponentProfile");
			Element peCmp = (Element) plCmp.item(0);

			NodeList plItem = peCmp.getElementsByTagName("identifier");
			int iNum = plItem.getLength();
			if(iNum==1)
			{
				Element peItem = (Element) plItem.item(0);
				if(peItem!=null)
				{
					strRes = peItem.getTextContent();
				}
			}

			// close file
			closeXmlFile(pDoc);
		}
		return strRes;
	}

	/**
	 * get a list of message names in Component profile.
	 * @param filename file path of Component profile
	 * @param type type of message (i.e.CommandMessageProfileType/QueryMessageProfileType/EventMessageProfileType)
	 * @param messages (out) list of message names
	 * @return
	 */
	public int getMessageNames(
		String filename,			// in :profile path
		String type,				// in :message type (command, )
		Vector<String> messages		// out:list of message names
	)
	{
		int iRes = 0;
		synchronized( m_hMutex )
		{
			// open file
			Document pDoc = openXmlFile(m_strDir+filename);
			if(pDoc==null)
			{
				return iRes;
			}

			// read xml file
			NodeList plCmp = pDoc.getElementsByTagName("HRIComponentProfile");
			Element peCmp = (Element) plCmp.item(0);

			NodeList plItem = peCmp.getElementsByTagName("MessageProfile");
			int iNum = plItem.getLength();
			for(int i=0; i<iNum; i++)
			{
				Element peItem = (Element) plItem.item(i);
				if(peItem!=null)
				{
					String strType = peItem.getAttribute("type");
					if(strType.matches(type))
					{
						String strTypeName = peItem.getAttribute("name");
						messages.add(strTypeName);
						iRes++;
					}
				}
			}

			// close file
			closeXmlFile(pDoc);
		}
		return iRes;
	}

	/**
	 * get a list of parameters of message in Component profile.
	 * @param filename file path of Component profile
	 * @param type type of message
	 * @param name message name
	 * @param names (out) list of parameter names
	 * @param datatypes (out) list of data type of the parameters
	 * @param defaultvalues (out) list of default value of the parameters
	 * @return number of parameters
	 */
	public int getMessageParameters(
		String filename,				// in :profile path
		String type,					// in :message type
		String name,					// in :message name
		Vector<String> names,			// out:list of parameter names
		Vector<String> datatypes,		// out:list of parameter datatypes
		Vector<String> defaultvalues	// out:list od parameter default values
	)
	{
		int iRes = 0;
		synchronized( m_hMutex )
		{
			// open file
			Document pDoc = openXmlFile(m_strDir+filename);
			if(pDoc==null)
			{
				return iRes;
			}

			// read xml file
			NodeList plCmp = pDoc.getElementsByTagName("HRIComponentProfile");
			Element peCmp = (Element) plCmp.item(0);

			NodeList plItem = peCmp.getElementsByTagName("MessageProfile");
			int iNum = plItem.getLength();
			for(int i=0; i<iNum; i++)
			{
				Element peItem = (Element) plItem.item(i);
				if(peItem!=null)
				{
					String strType = peItem.getAttribute("type");
					String strName = peItem.getAttribute("name");
					if(strType.matches(type) && strName.matches(name))
					{
						NodeList plParam = null;
						if(type=="CommandMessageProfileType")
						{
							plParam = peItem.getElementsByTagName("Arguments");
						}
						else
						{
							plParam = peItem.getElementsByTagName("Results");
						}
						iRes = getParameterElements(
							plParam,
							names,
							datatypes,
							defaultvalues
						);
					}
				}
			}

			// close file
			closeXmlFile(pDoc);
		}
		return iRes;
	}

	/**
	 * get component parameters in Component/Engine profile.
	 * @param filename file path of Component profile
	 * @param type profile type (i.e. HRIComponent/HRIEngine)
	 * @param names (out) list of parameter names
	 * @param datatypes (out) list of data type of the parameters
	 * @param defaultvalues (out) list of default value of the parameters
	 * @return number of parameters
	 */
	public int getParameters(
		String filename,				// in :profile path
		String type,					// in :profile type(HRIComponent/HRIEngine)
		Vector<String> names,			// out:list of parameter names
		Vector<String> datatypes,		// out:list of parameter datatypes
		Vector<String> defaultvalues	// out:list od parameter default values
	)
	{
		int iRes = 0;
		synchronized( m_hMutex )
		{
			// open file
			Document pDoc = openXmlFile(m_strDir+filename);
			if(pDoc==null)
			{
				return iRes;
			}

			// read xml file
			NodeList plCmp = pDoc.getElementsByTagName(type);
			Element peCmp = (Element) plCmp.item(0);

			NodeList plItem = peCmp.getElementsByTagName("ParameterProfile");
			int iNum = plItem.getLength();
			if(iNum!=0)
			{
				iRes = getParameterElements(
						plItem,
						names,
						datatypes,
						defaultvalues
				);
			}

			// close file
			closeXmlFile(pDoc);
		}
		return iRes;
	}

	/**
	 * (INTERNAL USE ONLY) get attribute of a parameter
	 * @param plItem XML element object of the parameter profile
	 * @param names (out) list of parameter names
	 * @param datatypes (out) list of data type of the parameters
	 * @param defaultvalues (out) list of default value of the parameters
	 * @return number of parameters
	 */
	public int getParameterElements(
		NodeList plItem,				// in :node list pointer
		Vector<String> names,			// out:list of parameter names
		Vector<String> datatypes,		// out:list of parameter datatypes
		Vector<String> defaultvalues	// out:list od parameter default values
	)
	{
		int iRes = plItem.getLength();
		for(int i=0; i<iRes; i++)
		{
			Element peItem = (Element) plItem.item(i);
			if(peItem!=null)
			{
				// name
				String strName = peItem.getAttribute("name");
				names.add(strName);
				// default value
				String strValue = peItem.getAttribute("default_value");
				defaultvalues.add(strValue);
				// data type
				NodeList plType = peItem.getElementsByTagName("data_type_ref");
				int iTemp = plType.getLength();
				if(iTemp!=0)
				{
					Element peType = (Element) plType.item(0);		// use first child
					String strType = peType.getAttribute("code");
					datatypes.add(strType);
				}
				else
				{
					datatypes.add("");
				}
			}
		}
		return iRes;
	}

	//////////////////////////////////////////////////
	// for internal data object
	//////////////////////////////////////////////////
	/**
	 * reset RoIS_Components object.
	 */
	public void resetProfiles()
	{
		m_Components.clear();
	}

	/**
	 * load Component profile data into RoIS_Component object.
	 * @param filename file path of Component profile
	 * @param component_refs component reference ID
	 */
	public void loadComponentProfile(
		String filename,			// in : component profile file name
		String component_refs		// in : component ID
	)
	{
		// check HRI Component Profile
		String strCompName;
		strCompName = getComponentName(
			filename
		);

		int comp_index = m_Components.getIndexByReferenceid(component_refs);
		if(comp_index==-1)
		{
			m_Components.push_back(
				false,					// connection status
				"",						// nameservice
				"",						// servername (=referenceid)
				strCompName,			// name
				component_refs			// referenceid (=servername)
			);
			comp_index = m_Components.getIndexByReferenceid(component_refs);
		}

		// check sub HRI Component Profile
		Vector<String> strSubCompFiles = new Vector<String>();
		if(isSubComponentProfile(filename))
		{
			strSubCompFiles.clear();
			int sub_comp_size = getSubComponentProfiles(
				filename,
				strSubCompFiles
			);
			String strFile;
			for(int i=0; i<sub_comp_size; i++)
			{
				strFile = strSubCompFiles.get(i);
				loadComponentProfile(
					strFile,
					component_refs
				);
			}
		}

		// check Message Profile
		Vector<String> strMsgNames = new Vector<String>();
		Vector<String> strPrmNames = new Vector<String>();
		Vector<String> strPrmDataTypes = new Vector<String>();
		Vector<String> strPrmDefaultValue = new Vector<String>();
		int msg_size;
		int current_msg_index;
		int param_size;

		// check Command Message Profile
		msg_size = 0;
		current_msg_index = m_Components.command_message.get(comp_index).size;
		strMsgNames.clear();
		msg_size = getMessageNames(
			filename,
			"CommandMessageProfileType",
			strMsgNames
		);
		for(int i=0; i<msg_size; i++)
		{
			m_Components.command_message.get(comp_index).push_back(
				strMsgNames.get(i),
				""
			);
			strPrmNames.clear();
			strPrmDataTypes.clear();
			strPrmDefaultValue.clear();
			param_size = 0;
			param_size = getMessageParameters(
				filename,
				"CommandMessageProfileType",
				strMsgNames.get(i),
				strPrmNames,
				strPrmDataTypes,
				strPrmDefaultValue
			);
			for(int j=0; j<param_size; j++)
			{
				m_Components.command_message.get(comp_index).parameters.get(i+current_msg_index).push_back(
					strPrmNames.get(j),
					strPrmDataTypes.get(j),
					strPrmDefaultValue.get(j)
				);
			}
		}

		// check Query Message Profile
		msg_size = 0;
		current_msg_index = m_Components.query_message.get(comp_index).size;
		strMsgNames.clear();
		msg_size = getMessageNames(
			filename,
			"QueryMessageProfileType",
			strMsgNames
		);
		for(int i=0; i<msg_size; i++)
		{
			m_Components.query_message.get(comp_index).push_back(
				strMsgNames.get(i),
				""
			);
			strPrmNames.clear();
			strPrmDataTypes.clear();
			strPrmDefaultValue.clear();
			param_size = 0;
			param_size = getMessageParameters(
				filename,
				"QueryMessageProfileType",
				strMsgNames.get(i),
				strPrmNames,
				strPrmDataTypes,
				strPrmDefaultValue
			);
			for(int j=0; j<param_size; j++)
			{
				m_Components.query_message.get(comp_index).parameters.get(i+current_msg_index).push_back(
					strPrmNames.get(j),
					strPrmDataTypes.get(j),
					strPrmDefaultValue.get(j)
				);
			}
		}

		// check Event Message Profile
		msg_size = 0;
		current_msg_index = m_Components.event_message.get(comp_index).size;
		strMsgNames.clear();
		msg_size = getMessageNames(
			filename,
			"EventMessageProfileType",
			strMsgNames
		);
		for(int i=0; i<msg_size; i++)
		{
			m_Components.event_message.get(comp_index).push_back(
				strMsgNames.get(i),
				""
			);
			strPrmNames.clear();
			strPrmDataTypes.clear();
			strPrmDefaultValue.clear();
			param_size = 0;
			param_size = getMessageParameters(
				filename,
				"EventMessageProfileType",
				strMsgNames.get(i),
				strPrmNames,
				strPrmDataTypes,
				strPrmDefaultValue
			);
			for(int j=0; j<param_size; j++)
			{
				m_Components.event_message.get(comp_index).parameters.get(i+current_msg_index).push_back(
					strPrmNames.get(j),
					strPrmDataTypes.get(j),
					strPrmDefaultValue.get(j)
				);
			}
		}
		return;
	}

	/**
	 * load Parameter profile data into RoIS_Component object.
	 * @param filename file path of Component profile
	 * @param component_refs component reference ID
	 */
	public void loadComponentParameterProfile(
		String filename,			// in : component profile file name
		String component_refs		// out: component ID
	)
	{
		// check HRI Component Profile
		String strCompName;
		strCompName = getComponentName(
			filename
		);

		int comp_index = m_Components.getIndexByReferenceid(component_refs);
		if(comp_index==-1)
		{
			m_Components.push_back(
				false,					// connection status
				"",						// nameservice
				"",						// servername (=referenceid)
				strCompName,			// name
				component_refs			// referenceid (=servername)
			);
			comp_index = m_Components.getIndexByReferenceid(component_refs);
		}

		// check sub HRI Component Profile
		Vector<String> strSubCompFiles = new Vector<String>();
		if(isSubComponentProfile(filename))
		{
			strSubCompFiles.clear();
			int sub_comp_size = getSubComponentProfiles(
				filename,
				strSubCompFiles
			);
			String strFile;
			for(int i=0; i<sub_comp_size; i++)
			{
				strFile = strSubCompFiles.get(i);
				loadComponentParameterProfile(
					strFile,
					component_refs
				);
			}
		}

		// check Parameter Profile
		Vector<String> strPrmNames = new Vector<String>();
		Vector<String> strPrmDataTypes = new Vector<String>();
		Vector<String> strPrmDefaultValue = new Vector<String>();
		strPrmNames.clear();
		strPrmDataTypes.clear();
		strPrmDefaultValue.clear();
		int msg_size = 0;
		msg_size = getParameters(
			filename,
			"HRIComponentProfile",
			strPrmNames,
			strPrmDataTypes,
			strPrmDefaultValue
		);
		for(int i=0; i<msg_size; i++)
		{
			m_Components.parameter.get(comp_index).push_back(
				strPrmNames.get(i),
				strPrmDataTypes.get(i),
				strPrmDefaultValue.get(i)
			);
		}
		return;
	}

	//////////////////////////////////////////////////
	// for internal data operation
	//////////////////////////////////////////////////
	/**
	 * (INTERNAL USE ONLY) add RoIS::ComponentProfile object into RoIS_Component object.
	 * @param profile ComponentProfile object
	 */
	public void addComponentProfile(
		ComponentProfileHolder profile	// in : ComponentProfile structure
	)
	{
		// check HRI Component Profile
		ComponentProfile _profile;
		_profile = profile.value;
		String strCompServName = _profile.servername;
		String strCompType = _profile.name;
		String strCompID = _profile.reference_id;

		int comp_index = m_Components.getIndexByReferenceid(strCompID);
		if(comp_index == -1)
		{
			m_Components.push_back(
				false,			// connection status
				"",				// nameservice
				strCompServName,// servername
				strCompType,	// type
				strCompID		// referenceid
			);
			comp_index = m_Components.getIndexByReferenceid(strCompID);
		}

		int msg_size;
		int param_size;

		// check Command Message Profile
		msg_size = _profile.command_message.length;
		for(int i=0; i<msg_size; i++)
		{
			m_Components.command_message.get(comp_index).push_back(
				_profile.command_message[i].name,
				_profile.command_message[i].id
			);
			param_size = _profile.command_message[i].parameters.length;
			for(int j=0; j<param_size; j++)
			{
				//@@ FOR DUMMY: treat "any" as "string" (tentatively)
				m_Components.command_message.get(comp_index).parameters.get(i).push_back(
					_profile.command_message[i].parameters[j].name,
					_profile.command_message[i].parameters[j].data_type_ref,
					_profile.command_message[i].parameters[j].value.extract_string()
				);
			}
		}
		// check Query Message Profile
		msg_size = _profile.query_message.length;
		for(int i=0; i<msg_size; i++)
		{
			m_Components.query_message.get(comp_index).push_back(
				_profile.query_message[i].name,
				_profile.query_message[i].id
			);
			param_size = _profile.query_message[i].parameters.length;
			for(int j=0; j<param_size; j++)
			{
				//@@ FOR DUMMY: treat "any" as "string" (tentatively)
				m_Components.query_message.get(comp_index).parameters.get(i).push_back(
					_profile.query_message[i].parameters[j].name,
					_profile.query_message[i].parameters[j].data_type_ref,
					_profile.query_message[i].parameters[j].value.extract_string()
				);
			}
		}
		// check Event Message Profile
		msg_size = _profile.event_message.length;
		for(int i=0; i<msg_size; i++)
		{
			m_Components.event_message.get(comp_index).push_back(
				_profile.event_message[i].name,
				_profile.event_message[i].id
			);
			param_size = _profile.event_message[i].parameters.length;
			for(int j=0; j<param_size; j++)
			{
				//@@ FOR DUMMY: treat "any" as "string" (tentatively)
				m_Components.event_message.get(comp_index).parameters.get(i).push_back(
					_profile.event_message[i].parameters[j].name,
					_profile.event_message[i].parameters[j].data_type_ref,
					_profile.event_message[i].parameters[j].value.extract_string()
				);
			}
		}
		// check Parameter Profile
		param_size = _profile.parameter.length;
		for(int i=0; i<param_size; i++)
		{
			//@@ FOR DUMMY: treat "any" as "string" (tentatively)
			m_Components.parameter.get(comp_index).push_back(
				_profile.parameter[i].name,
				_profile.parameter[i].data_type_ref,
				_profile.parameter[i].value.extract_string()
			);
		}
		return;
	}

	/**
	 * (INTERNAL USE ONLY) remove Component data from RoIS_Components object.
	 * @param component_ref reference ID of the component
	 */
	public void eraseComponentProfile(
		String component_ref		// in: component ID
	)
	{
		int comp_index = m_Components.getIndexByReferenceid(component_ref);
		if(comp_index == -1)
		{
			return;
		}
		m_Components.erase(comp_index);
		return;
	}

	/**
	 * get number of Components in RoIS_Componet object.
	 * @return number of Components
	 */
	public int getComponentSize()
	{
		int iRes = 0;
		iRes = m_Components.size;
		return iRes;
	}

	/**
	 * get Component reference ID related to server name.
	 * @param servername CORBA server name of the Component
	 * @return reference ID
	 */
	String getComponentRefByServername(
		String servername			// in servername
	)
	{
		String strRes = "";
		int index = m_Components.getIndexByServername(servername);
		if(index!=-1)
		{
			strRes = m_Components.referenceid.get(index);
		}
		return strRes;
	}

	/**
	 * get Component name related to server name.
	 * @param servername CORBA server name of the Component
	 * @return Component name
	 */
	public String getComponentNameByServername(
		String servername			// in servername
	)
	{
		String strRes = "";
		int index = m_Components.getIndexByServername(servername);
		if(index!=-1)
		{
			strRes = m_Components.name.get(index);
		}
		return strRes;
	}

	/**
	 * get Component reference ID related to index.
	 * @param index index of the Component
	 * @return reference ID
	 */
	public String getComponentRefByIndex(
		int index						// in: component index
	)
	{
		String strRes = "";
		if(0<=index && index<m_Components.size)
		{
			strRes = m_Components.referenceid.get(index);
		}
		return strRes;
	}

	/**
	 * get server name related to Component reference ID.
	 * @param component_ref reference ID of the component
	 * @return server name
	 */
	public String getServernameByComponentRef(
		String component_ref		// in component_ref
	)
	{
		String strRes = "";
		int index = m_Components.getIndexByReferenceid(component_ref);
		if(index!=-1)
		{
			strRes = m_Components.servername.get(index);
		}
		return strRes;
	}

	/**
	 * check presence of condition string in a target string.
	 * @param target target text
	 * @param condition condition text
	 * @return true/false
	 */
	public boolean searchString(
		String target,				// in : target string
		String condition			// out: condition
	)
	{
		boolean bRes = false;
		String strTarget = target;
		if(strTarget.startsWith(condition))
		{
			bRes = true;
		}
		return bRes;
	}

	/**
	 * search Component including condition string in component name
	 * @param condition condition test
	 * @param component_refs (out) list of reference ID of components
	 * @return number of components
	 */
	public int searchComponent(
		String condition,				// in : condition
		Vector<String> component_refs	// out: list of component_refs
	)
	{
		int iRes = 0;
		component_refs.clear();
		//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
		//@@ FOR DUMMY: check profiles
		int comp_size = m_Components.size;
		for(int i=0; i<comp_size; i++)
		{
			// search string in condition from "component name"
			if( searchString(
				m_Components.name.get(i),
				condition
			))
			{
				component_refs.add(m_Components.referenceid.get(i));
			}
		}
		//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
		iRes = component_refs.size();
		return iRes;
	}

	/**
	 * search Component including condition string in component name
	 * that holds specified query message
	 * @param query_type query type
	 * @param condition condition text
	 * @param component_refs (out) list of reference ID of components
	 * @return number of components
	 */
	public int searchQueryType(
		String query_type,				// in : query type
		String condition,				// in : condition
		Vector<String> component_refs	// out: list of component_refs
	)
	{
		int iRes = 0;
		component_refs.clear();
		//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
		//@@ FOR DUMMY: check profiles
		Vector<String> strCompRefList = new Vector<String>();
		strCompRefList.clear();
		int conditional_size = 0;
		conditional_size = searchComponent(
			condition,
			strCompRefList
		);
		//@@ FOR DUMMY: return all component reference IDs when there is no candidate
		int comp_size = m_Components.size;
		if(conditional_size==0)
		{
			for(int i=0; i<comp_size; i++)
			{
				strCompRefList.add(m_Components.referenceid.get(i));
				conditional_size++;
			}
		}
		//@@ FOR DUMMY: check query type in profiles
		int comp_index = -1;
		for(int i=0; i<conditional_size; i++)
		{
			comp_index = -1;
			comp_index = m_Components.getIndexByReferenceid(strCompRefList.get(i));
			if(comp_index!=-1)
			{
				// check parameters of the message
				int msg_size = m_Components.query_message.get(comp_index).size;
				for(int j=0; j<msg_size; j++)
				{
					// check name of the message in the profile
					if(m_Components.query_message.get(comp_index).type.get(j)==query_type)
					{
						component_refs.add(strCompRefList.get(i));
					}
				}
			}
		}
		//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
		iRes = component_refs.size();
		return iRes;
	}

	/**
	 * search Component including condition string in component name
	 * that holds specified event message.
	 * @param event_type event type
	 * @param condition condition text
	 * @param component_refs (out) list of reference ID of components
	 * @return number of components
	 */
	public int searchEventType(
		String event_type,				// in : event type
		String condition,				// in : condition
		Vector<String> component_refs	// out: list of component_refs
	)
	{
		int iRes = 0;
		component_refs.clear();
		//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
		//@@ FOR DUMMY: check profiles
		Vector<String> strCompRefList = new Vector<String>();
		strCompRefList.clear();
		int conditional_size = 0;
		conditional_size = searchComponent(
			condition,
			strCompRefList
		);
		//@@ FOR DUMMY: return all components when there is no candidate
		int comp_size = m_Components.size;
		if(conditional_size==0)
		{
			for(int i=0; i<comp_size; i++)
			{
				strCompRefList.add(m_Components.referenceid.get(i));
				conditional_size++;
			}
		}
		//@@ FOR DUMMY: check event type in profile
		int comp_index = -1;
		for(int i=0; i<conditional_size; i++)
		{
			comp_index = -1;
			comp_index = m_Components.getIndexByReferenceid(strCompRefList.get(i));
			if(comp_index!=-1)
			{
				// check parameters of the message
				int msg_size = m_Components.event_message.get(comp_index).size;
				for(int j=0; j<msg_size; j++)
				{
					// check name of the message
					if(m_Components.event_message.get(comp_index).type.get(j)==event_type)
					{
						component_refs.add(strCompRefList.get(i));
					}
				}
			}
		}
		//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
		iRes = component_refs.size();
		return iRes;
	}

	/**
	 * get index of query message and component.
	 * @param component_ref reference ID of the component
	 * @param query_type query type
	 * @param component_index (out) index of the component
	 * @param message_index (out) index of the query message
	 * @param parameter_size (out) size of parameters in the query message
	 * @return true/false
	 */
	public boolean getQueryMessageIndex(
		String component_ref,		// in : component_ref
		String query_type,			// in : query type
		int component_index,		// out: component index
		Integer message_index,		// out: message index
		Integer parameter_size		// out: parameter size
	)
	{
		boolean bRes = false;
		component_index = -1;
		message_index = -1;
		parameter_size = 0;
		// check component
		component_index = m_Components.getIndexByReferenceid(component_ref);
		if(component_index==-1)
		{
			return bRes;
		}
		// check query_type
		int msg_size = m_Components.query_message.get(component_index).size;
		for(int i=0; i<msg_size; i++)
		{
			if(m_Components.query_message.get(component_index).type.get(i)==query_type)
			{
				message_index = i;
				parameter_size = m_Components.query_message.get(component_index).parameters.get(message_index).size;
				bRes = true;
				break;
			}
		}
		return bRes;
	}

	/**
	 * get index of query message and component.
	 * @param component_ref reference ID of the component
	 * @param command_type command type
	 * @param component_index (out) index of the component
	 * @param message_index (out) index of the query message
	 * @param parameter_size (out) size of parameters in the query message
	 * @return true/false
	 */
	public boolean getCommandMessageIndex(
		String component_ref,		// in : component_ref
		String command_type,		// in : command type
		Integer component_index,			// out: component index
		Integer message_index,				// out: message index
		Integer parameter_size				// out: parameter size
	)
	{
		boolean bRes = false;
		component_index = -1;
		message_index = -1;
		parameter_size = 0;
		// check component
		component_index = m_Components.getIndexByReferenceid(component_ref);
		if(component_index==-1)
		{
			return bRes;
		}
		// check command_type
		int msg_size = m_Components.command_message.get(component_index).size;
		for(int i=0; i<msg_size; i++)
		{
			if(m_Components.command_message.get(component_index).type.get(i)==command_type)
			{
				message_index = i;
				parameter_size = m_Components.command_message.get(component_index).parameters.get(message_index).size;
				bRes = true;
				break;
			}
		}
		return bRes;
	}

	/**
	 * get index of query message and component.
	 * @param component_ref reference ID of the component
	 * @param event_type event type
	 * @param component_index (out) index of the component
	 * @param message_index (out) index of the query message
	 * @param parameter_size (out) size of parameters in the query message
	 * @return true/false
	 */
	public boolean getEventMessageIndex(
		String component_ref,		// in : component_ref
		String event_type,			// in : event type
		Integer component_index,			// out: component index
		Integer message_index,				// out: message index
		Integer parameter_size				// out: parameter size
	)
	{
		boolean bRes = false;
		component_index = -1;
		message_index = -1;
		parameter_size = 0;
		// check component
		component_index = m_Components.getIndexByReferenceid(component_ref);
		if(component_index==-1)
		{
			return bRes;
		}
		// check event_type
		int msg_size = m_Components.event_message.get(component_index).size;
		for(int i=0; i<msg_size; i++)
		{
			if(m_Components.event_message.get(component_index).type.get(i)==event_type)
			{
				message_index = i;
				parameter_size = m_Components.event_message.get(component_index).parameters.get(message_index).size;
				bRes = true;
				break;
			}
		}
		return bRes;
	}
}
